//
//  RACCommandVC.m
//  ReactiveObjCDemo
//
//  Created by xth on 2017/12/10.
//  Copyright © 2017年 xth. All rights reserved.
//

#import "RACCommandVC.h"

@interface RACCommandVC ()

@property (nonatomic, strong) RACCommand *command;

@end

@implementation RACCommandVC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [self createRACCommand];
}

/*
 RACCommand:RAC中用于处理事件的类，可以把事件如何处理，事件中的数据如何传递，包装到这个类中，可以很方便的监控事件的执行过程
 
 使用步骤：
 1.创建命令 initWithSignalBlock:(RACAignal * (^)(id input))signalBlock
 2.在signalBlock中，创建RACSignal，作为signalBlock的返回值
 3.执行命令 - (RACSignal *)excute:(idinput)
 
 RACCommand使用注意：
 1.signalBlock必须要返回一个信号，不能传nil.
 2.如果不想要传递信号，直接创建空的信号 [RACSignal empty];
 3.RACCommand中信号如果数据传递完，必须要调用[subscriber sendCompleted]，这时命令才会执行完毕，否则永远处于执行中
 4.RACCommand需要被强引用，否则接收不到RACCommand中的信号，因此RACCommand中的信号是延迟发送的。
 
 RACCommand设计思想：内部signalBlock为什么要返回一个信号，这个信号有什么用。
 1.在RAC开发中，通常会把网络请求封装到RACCommand中，直接执行某个RACCommand就能发送请求
 2.当RACCommand内部请求到数据的时候，需要把请求的数据传递给外界，这时候就需要通过signalBlock返回信号传递了
 
 如何拿到RACCommand中返回信号发出的数据
 1.RACCommand有个执行信号源executionSignals，这个signal of signals（信号的信号），意思是信号发出的数据是信号，不是普通的类型
 2.订阅executionSignals就能拿到RACCommand中返回的信号，然后订阅signalBlock返回的信号，就能获取发出的值
 
 监听当前命令是否正在执行executing
 
 使用场景，监听按钮点击，网络请求
 
*/

- (void)createRACCommand {
    
    //1.创建命令
    RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        NSLog(@"执行命令");
        
        //传经空信号，必须返回信号
//        return [RACSignal empty];
        
        //2.创建信号
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            
            [subscriber sendNext:@"@{'name': '逗比'}"];
            
            //注意：数据传递完，最好调用completed，这时命令才执行完毕
            [subscriber sendCompleted];
            
            return nil;
        }];
    }];
    
    
    //强引用命令，不要被销毁，否则接收不到数据
    _command = command;
    
    //默认会来一次
    [_command.executionSignals subscribeNext:^(id  _Nullable x) {
        [x subscribeNext:^(id  _Nullable x) {
            NSLog(@"收到数据：%@", x);
        }];
    }];
    
    //高级用法
    // switchToLatest:用于signal of signals，获取signal of signals发出的最新信号,也就是可以直接拿到RACCommand中的信号
    [_command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
        NSLog(@"executionSignals.switchToLatest:%@",x);
    }];
    
    //监听命令是否执行完毕，返回YES or NO 可以直接跳过，skip表示跳过第一次信号。
    [[_command.executing skip:1] subscribeNext:^(NSNumber * _Nullable x) {
        if ([x isEqualToNumber:@(YES)]) {
            NSLog(@"正在执行");
        } else {
            NSLog(@"执行完毕");
        }
    }];
    
    //3.执行命令
    [_command execute:nil];
}








- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
